/**
 * 输出图像
 * ibio-develop
 * 2009-3-3 17:50
 */
package com.ibio8.media.image {
	import com.adobe.images.JPGEncoder;
	import com.adobe.images.PNGEncoder;
	
	import flash.display.IBitmapDrawable;
	import flash.display.DisplayObject;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.net.URLRequest;
	import flash.net.URLLoader;
	import flash.net.URLRequestMethod;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
	import flash.geom.Matrix;
	import flash.utils.ByteArray;
	/**
	 * 输出图像类。
	 * 
	 * <p>
	 * 此类是对于 BitmapData 进行 jpg、png 压缩并输出图像的集合类。
	 * </p>
	 */
	public class PrintImage {
		/** 由 jpg 格式压缩 **/
		public static const JPG:String = "JPGEncoder";
		/** 由 png 格式压缩 **/
		public static const PNG:String = "PNGEncoder";
		/** 由 压缩质量 **/
		public static const QUALITY:uint = 80;
		/** @private **/
		protected static var m_image:DisplayObject;
		/** @private **/
		protected static var m_degree:Number = 0;
		/** @private **/
		protected static var m_encodeMode:String = JPG;
		/** @private **/
		protected static var m_quality:uint = QUALITY;
		
		/**
		 * 设置源
		 * @param	value	要输出的源
		 * 因为 60 行需要用到 m_image.width 等，所以这里不能是 IBitmapDrawable
		 */
		public static function set source(value:DisplayObject):void {
			m_image = value;
		}
		
		/**
		 * 设置角度
		 * @param	degree	角度
		 */
		public static function set rotation(degree:Number):void {
			m_degree = degree;
		}
		
		/**
		 * 设置图像编码模式和JPG编码质量
		 * @param	mode	JPG/PNG
		 * @param	quality	default QUALITY
		 */
		public static function setEncodeMode(mode:String, quality:uint = QUALITY):void {
			m_encodeMode = mode;
			m_quality = quality;
		}
		
		/**
		 * 设置输出（POST）的 url，通常用于上传。
		 * @param	url	输出到此 url 的地方。
		 */
		public static function printToURL(url:String):void {
			var bitmapData:BitmapData = convert(m_image, m_image.width, m_image.height, m_degree);
			var imgStream:ByteArray = encode(bitmapData, m_encodeMode, m_quality);
			postData(url, imgStream);
		}
		
		/**
		 * 运用 POST 方式将二进制的图片流输出到指定 url
		 * @param	url				指定的 url
		 * @param	imgStream		二进制的图片流
		 * @param	resultCallback	成功回调函数
		 * @param	errorCallback	失败回调函数
		 */
		public static function postData(url:String, imgStream:ByteArray, resultCallback:Function = null, errorCallback:Function = null):void {
			var loader:URLLoader = new URLLoader();
			var request:URLRequest = new URLRequest(url);
			//内容类型必须是下面文件流形式
			request.contentType = "application/octet-stream";
			request.method = URLRequestMethod.POST;
			request.data = imgStream;
			//返回
			if (resultCallback != null) {
				loader.addEventListener(Event.COMPLETE, resultCallback, false, 0, true);
			}
			//错误
			if (errorCallback != null) {
				loader.addEventListener(IOErrorEvent.IO_ERROR, errorCallback, false, 0, true);
				loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorCallback, false, 0, true);
			}
			try {
				loader.load(request);
			}catch (e:Error) {
				trace(e.message);
			}
		}
		
		/**
		 * 将 BitmapData 编码成二进制流
		 * @param	bitmapData	源
		 * @param	mode		编码压缩方式，是采用 jpg 还是 png
		 * @param	quality		压缩质量
		 * @return				二进制流
		 */
		public static function encode(bitmapData:BitmapData, mode:String = JPG, quality:uint = QUALITY):ByteArray {
			var imgStream:ByteArray;
			switch (mode) {
				case JPG:
					var jpgEncoder:JPGEncoder = new JPGEncoder(quality);
					imgStream = jpgEncoder.encode(bitmapData);
					break;
				case PNG:
					imgStream = PNGEncoder.encode(bitmapData);
					break;
				default:
					break;
			}
			return imgStream;
		}
		
		/**
		 * 转换源
		 * @param	image	源（Bitmapdata/DisplayObject）
		 * @param	w		源的宽度
		 * @param	h		源的高度
		 * @param	sx		x 缩放
		 * @param	sy		y 缩放
		 * @param	degree	转换的度数
		 * @return			转换后的数据
		 */
		public static function convert(image:IBitmapDrawable, w:Number, h:Number, sx:Number = 1, sy:Number = 1, degree:Number = 0):BitmapData {
			var myMatrix:Matrix = new Matrix();
			var rotateMode:uint = 0;
			//转换为弧度
			var radians:Number = degree * Math.PI / 180;
			//位移转换
			var tx:Number = 0;
			var ty:Number = 0;
			//目前仅支持 4 个方向
			//因为这里有可能为负数，例如 -90，所以要加上 360
			if (Math.abs((degree + 360) % 360) == 0) {
				rotateMode = 0;
			}else if (Math.abs((degree + 360) % 360) == 90) {
				rotateMode = 1;
				tx = h;
			}else if (Math.abs((degree + 360) % 360) == 180) {
				rotateMode = 2;
				tx = w;
				ty = h;
			}else if (Math.abs((degree + 360) % 360) == 270) {
				rotateMode = 3;
				ty = w;
			}
			myMatrix.createBox(sx, sy, radians, tx, ty);
			//大小转换
			var width:Number = 0;
			var height:Number = 0;
			if ((rotateMode == 0) || (rotateMode == 2)) {
				width = w;
				height = h;
			}else if ((rotateMode == 1) || (rotateMode == 3)) {
				width = h;
				height = w;
			}
			var bitmapData:BitmapData = new BitmapData(width, height);
			bitmapData.draw(image, myMatrix, null, null, null, true);
			return bitmapData;
		}
		
		/**
		 * 返回当前源的字符串内容
		 * @return	当前源的字符串
		 */
		public static function toString():String {
			var bitmapData:BitmapData = convert(m_image, m_image.width, m_image.height, m_degree);
			var imgStream:ByteArray = encode(bitmapData, m_encodeMode, m_quality);
			return imgStream.toString();
		}
	}
}